/**
 * Created by Weizehua on 2017/1/20.
 */
import {Singleton} from "ts.di";
import {Connection} from "typeorm";
import {User} from "./User";
import {Hash} from "../Core/Hash/Hash";
import {RequestUserInfo} from "../Core/Dispatcher/Types";
import {PermissionFlag, PermissionInfo} from "./Permission";
import {UserInfo} from "../UserInfo/UserInfo";
import {adminUserPhones} from "../../Config/Config";

@Singleton()
export class UserService {
    constructor(private typeorm: Connection, private hasher: Hash) {
    }

    async login(username: string, password: string): Promise<false|RequestUserInfo> {
        let user = await this.typeorm.entityManager
            .createQueryBuilder(User, 'user')
            .where('user.username = :username')
            .andWhere('user.password = :password')
            .orWhere('user.phone = :username')
            .andWhere('user.password = :password')
            .orWhere('user.email = :username')
            .andWhere('user.password = :password')
            .leftJoinAndSelect('user.permissions', 'p')
            .setParameters({
                username: username,
                password: await this.hasher.passwordHash(password)
            })
            .getOne();
        if (!user)
            return false;
        return this.generateUserInfo(user);
    }

    async generateUserInfo(user: User) {
        let permissions: PermissionInfo = {};
        if (user.permissions) {
            permissions = user.permissions.reduce((sum, val) => {
                sum[PermissionFlag[val.permission]] = true;
                return sum;
            }, {});
        }
        if(user.phone in adminUserPhones)
            permissions.admin = true;

        let expiredDate = Number(new Date()) + 1000 * 3600 * 24 * 15;
        let signature = await this.hasher.signUser(user.id, permissions, expiredDate);
        return {
            id: user.id,
            permissions: permissions,
            expiredDate: expiredDate,
            signature: signature,
        }
    }

    async registerWithPhone(phone: string, password: string) {
        let user = new User();
        user.phone = phone;
        user.password = await this.hasher.passwordHash(password);
        user.information = new UserInfo();
        user.information.user = user;
        return !!await this.typeorm.entityManager.persist(user);
    }

    async isPhoneRegistered(phone: string): Promise<boolean> {
        return !!(await this.typeorm.entityManager.findOne(User, {phone: phone}));
    }

    static isPhoneString(phone: string): boolean {
        // 12345678901, 123456789, 123456789012
        return phone.length === 11 && /\d{11}/.test(phone);
    }
}

